﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace Antioch.Base.PlayerStates
{
    internal class Run : IState
    {
        public void Enter(StateMachine Machine)
        {
            Machine.DrawComponent.Play("Run", true);
            Machine.PhysicsComponent.PhysicsBody.GetFixtureList().SetFriction(0.8f);
        }

        public void Leave(StateMachine Machine)
        {
            
        }

        public void Update(StateMachine Machine)
        {
            //if (Machine.Input.Hurt)
            //{
            //    Machine.Transition(typeof(Flinch));
            //    return;
            //}

            if (Machine.PhysicsComponent.TimeSinceOnGround > 10)
            {
                Machine.Transition(typeof(Fall));
                return;
            }

            if (Machine.Input.NavigationStick.X == 0)
            {
                Machine.Transition(typeof(Stand));
                return;
            }

            if (Jemgine.Math.Vector.AlmostZero(Machine.Input.RawAimStick))
            {
                if (Machine.Input.NavigationStick.X > 0)
                    Machine.PlayerEntity.Facing = Jemgine.Data.Facings.Right;
                else if (Machine.Input.NavigationStick.X < 0)
                    Machine.PlayerEntity.Facing = Jemgine.Data.Facings.Left;
            }
            else
            {
                if (Machine.Input.RawAimStick.X > 0)
                {
                    Machine.PlayerEntity.Facing = Jemgine.Data.Facings.Right;
                    if (Machine.Input.NavigationStick.X < 0)
                    {
                        Machine.Transition(typeof(RunBackwards));
                        return;
                    }
                }
                else if (Machine.Input.RawAimStick.X < 0)
                {
                    Machine.PlayerEntity.Facing = Jemgine.Data.Facings.Left;
                    if (Machine.Input.NavigationStick.X > 0)
                    {
                        Machine.Transition(typeof(RunBackwards));
                        return;
                    }
                }
            }

            Vector2 Right = Jemgine.Math.Vector.Perpendicular(Machine.PhysicsComponent.GroundNormal);
            Right.Normalize();
            Machine.PhysicsComponent.PhysicsBody.ApplyLinearImpulse(Right * Machine.Settings.RunForce * Machine.Input.NavigationStick.X,
                Machine.PhysicsComponent.PhysicsBody.Position);

            if (Machine.Input.JumpPressed)
            {

                bool Climb = true;
                float Angle = Jemgine.Math.Angle.Normalize(Machine.PhysicsComponent.PhysicsBody.GetAngle());

                Vector2 Velocity = Machine.PhysicsComponent.PhysicsBody.GetLinearVelocity();
                Velocity = Vector2.Transform(Velocity, Matrix.CreateRotationZ(-Angle));

                switch (Machine.PlayerEntity.Facing)
                {
                    case Jemgine.Data.Facings.Right:
                        if (Velocity.X < 0) Climb = false;
                        break;
                    case Jemgine.Data.Facings.Left:
                        if (Velocity.X > 0) Climb = false;
                        break;
                }

                if (Climb)
                {
                    Vector2 GrabSpot = new Vector2(0, 0);
                    GrabSpot = Machine.PlayerEntity.TransformToWorldSpace(GrabSpot);

                    Jemgine.Math.OBB GrabBox = new Jemgine.Math.OBB();
                    GrabBox.Center = GrabSpot;
                    GrabBox.Extents = Machine.PhysicsComponent.Dimensions / 2;
                    GrabBox.Angle = Machine.PhysicsComponent.PhysicsBody.GetAngle();

                    List<PlayerNavigationNode> HitNodes = new List<PlayerNavigationNode>();

                    if (Machine.NavigationModule != null &&
                        Machine.NavigationModule.FindCollidingNodes(GrabBox, (A) => HitNodes.Add(A)) > 0)
                    {
                        LedgeHangPoint HangPoint = null;
                        foreach (var Node in HitNodes) if (Node is LedgeHangPoint) HangPoint = Node as LedgeHangPoint;
                        if (HangPoint == null) Climb = false;
                        else if (!HangPoint.CanHang(Machine.PlayerEntity)) Climb = false;

                        if (Climb)
                        {

                            Vector2 HangVector =
                                Vector2.Transform(HangPoint.Me.TransformToWorldSpace(HangPoint.Position)
                                - Machine.PhysicsComponent.PhysicsBody.Position, Matrix.CreateRotationZ(-Angle));

                            switch (Machine.PlayerEntity.Facing)
                            {
                                case Jemgine.Data.Facings.Left:
                                    if (HangVector.X > 0) Climb = false;
                                    break;
                                case Jemgine.Data.Facings.Right:
                                    if (HangVector.X < 0) Climb = false;
                                    break;
                            }

                        }

                        if (Climb)
                        {
                            Machine.Memory.LedgeHangPoint = HangPoint;
                            Machine.Transition(typeof(ClimbOntoLedge));
                        }
                    }
                    else
                        Climb = false;
                }


                if (!Climb)
                    Machine.Transition(typeof(Jump));
            }

        }
    }
}
